package cn.edu.njuit.webserver.securityserver.apis;

import antlr.Token;
import cn.edu.njuit.webserver.securityserver.common.Result;
import cn.edu.njuit.webserver.securityserver.config.WeChatProperties;
import cn.edu.njuit.webserver.securityserver.entity.UserAccount;
import cn.edu.njuit.webserver.securityserver.service.AccountService;
import cn.edu.njuit.webserver.securityserver.service.SmsService;
import cn.edu.njuit.webserver.securityserver.service.TokenService;
import cn.edu.njuit.webserver.securityserver.service.dto.UserToken;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import static cn.edu.njuit.webserver.securityserver.common.ResultCode.*;

@RestController
@RequestMapping("/api")
public class AccountController {
    private final AccountService accountService;

    public AccountController(AccountService accountService) {
        this.accountService = accountService;
    }

    @Autowired
    AuthenticationManagerBuilder authenticationManagerBuilder;

    @Autowired
    SmsService smsService;

    @Autowired
    RestTemplateBuilder restTemplateBuilder;

    @Autowired
    @Qualifier("JwtTokenService")
    TokenService tokenService;

    @Autowired
    WeChatProperties weChatProperties;


    @ApiOperation("注册新账户")
    @ApiImplicitParams({@ApiImplicitParam(name = "login", value = "登录名", required = true), @ApiImplicitParam(name = "password", value = "登录密码", required = true), @ApiImplicitParam(name = "defaultRole", value = "默认角色名", required = false)})
    @PostMapping("/regist")
    public Result registerAccount(@RequestParam(required = true) String login, @RequestParam(required = true) String password, @RequestParam(required = false, defaultValue = "role_user") String defaultRole) {
        try {
            UserAccount account = this.accountService.regAccount(login, password, defaultRole);
            return Result.success(account);
        } catch (Exception e) {
            e.printStackTrace();
            JSONObject error = new JSONObject();
            error.put("errorInfo", e.getMessage());
            return Result.failure(USER_SIGN_UP_FAIL, error);
        }
    }

    @ApiOperation("账户登录")
    @ApiImplicitParams({@ApiImplicitParam(name = "login", value = "登录名", required = true), @ApiImplicitParam(name = "password", value = "登录密码", required = true)})
    @PostMapping("/login")
    public Result doLogin(@RequestParam(required = true) String login, @RequestParam(required = true) String password) {

        User loginUser = null;
        try {
            //使用SpringSecurity框架进行登录
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(login, password);

            //使用springSecurity进行登录认真
            Authentication authenticate = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
            loginUser = (User) authenticate.getPrincipal();
        } catch (Exception e) {
            return Result.failure(USER_ACCOUNT_OR_PASSWORD_ERROR, "null");
        }


        try {
//            String token = this.accountService.doLogin(login, password);
            String token = tokenService.getToken(loginUser.getUsername());
            JSONObject result = new JSONObject();
            result.put("id_token", token);
            return Result.success(result);
        } catch (Exception e) {
            e.printStackTrace();
            JSONObject error = new JSONObject();
            error.put("errorInfo", e.getMessage());
            return Result.failure(USER_SIGN_IN_FAIL, error);
        }
    }

    @ApiOperation("分页获取全部账户")
    @GetMapping("/sys/accounts")
    public Result getAccounts(@RequestParam(required = false, defaultValue = "0") Integer page, @RequestParam(required = false, defaultValue = "10") Integer size) {
        Page<UserAccount> result = this.accountService.getAllAccounts(page, size);
        return Result.success(result);
    }

    @DeleteMapping("/sys/accounts")
    public Result deleteAccount(@RequestParam(required = true) String login) {
        try {
            boolean result = this.accountService.deleteAccount(login);
            return Result.success("删除成功");
        } catch (Exception e) {
            e.printStackTrace();
            JSONObject error = new JSONObject();
            error.put("errorInfo", e.getMessage());
            return Result.failure(DATABASE_ERROR, error);
        }
    }

    @ApiOperation("获取用户权限令牌")
    @GetMapping("/sys/userToken")
    public Result getUserToken(HttpServletRequest request, HttpServletResponse response) {
        try {
            String token = request.getHeader("Authorization");
            UserToken UserToken = tokenService.getUser(token);
            JSONObject result = new JSONObject();
            result.put("UserToken", UserToken);
            return Result.success(result);
        } catch (Exception e) {
            e.printStackTrace();
            JSONObject error = new JSONObject();
            error.put("errorInfo", e.getMessage());
            return Result.failure(TOKEN_EXPIRED, error);
        }
    }

    @GetMapping("/send-sms")
    public Result sendSms(String phone) {
        //根据⼿机号码查找账户信息
        UserAccount userAccount = this.accountService.getAccountByPhone(phone);
        Result r = new Result();
        //确定账户存在，发送短信验证码
        if (userAccount != null) {
            //发送验证码
            boolean result = this.smsService.sendValidateSms(phone);
            if (result) {
                return Result.success(result);
            } else {
                return Result.failure("验证码发送失败");
            }
        } else {
            return Result.failure("手机号码不存在");
        }
    }

    @PostMapping("/sms-login")
    public Result smsLogin(@RequestParam(required = true) String phone,
                           @RequestParam(required = true) String validateCode) {
        UserAccount userAccount = this.accountService.getAccountByPhone(phone);
        JSONObject jsonResult = new JSONObject();
        if (userAccount != null) {
            //校验输⼊的验证码
            boolean result = this.smsService.validateSms(phone, validateCode);
            //验证码校验成功，需要根据当前账户，构造jwt令牌返回。
            if (result) {
                String token = null;
                try {
                    //使⽤token服务，返回令牌
                    token = this.tokenService.getToken(userAccount.getLogin());
                    jsonResult.put("id_token", token);
                    return Result.success(jsonResult);
                } catch (Exception e) {
                    e.printStackTrace();
                    jsonResult.put("result", e.getMessage());
                    return Result.failure(RESULT_CODE_DATA_NONE, jsonResult);
                }
            } else {
                return Result.failure(USER_VERIFY_CODE_ERROR);
            }
        }
        //发⽣异常表示登录出错
        jsonResult.put("result", "手机号码不存在");
        return Result.failure(USER_SIGN_IN_FAIL, jsonResult);
    }

    @PostMapping("/wechatlogin")
    public Result wechatLogin(@RequestParam(required = true) String code) {
        //获取到⽤户微信平台的登录授权码
        RestTemplate restTemplate = this.restTemplateBuilder.build();
        //微信平台REST API地址
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" +
                weChatProperties.getAppid() +
                "&secret=" +
                weChatProperties.getAppSecret() +
                "&code=" +
                code +
                "&grant_type=authorization_code";
        //向微信开放平台发送请求，获取⽤户信息
        String result = restTemplate.getForObject(url, String.class);
        //解析微信平台返回的⽤户信息数据
        JSONObject wechatResult = JSONObject.parseObject(result);
        if (wechatResult.containsKey("openid")) {
            String openid = wechatResult.getString("openid");
            //从微信⽤户信息⾥获取⽤户openid，根据openid获取账户信息
            UserAccount userAccount = this.accountService.getAccountByOpenId(openid);
            if (userAccount != null) {
                JSONObject jsonResult = new JSONObject();
                try {
                    //使⽤token服务，⽣成账户令牌
                    String token = this.tokenService.getToken(userAccount.getLogin());
                    jsonResult.put("id_token", token);
                    return Result.success(jsonResult);
                } catch (Exception e) {
                    e.printStackTrace();
                    return Result.failure(RESULT_CODE_DATA_NONE, e.getMessage());
                }
            } else {
                JSONObject erroResult = new JSONObject();
                erroResult.put("error", "微信⽤户未绑定系统账户，请先绑定账户，微信openid为：" + openid);
                return Result.failure(SYSTEM_INNER_ERROR, erroResult);
            }
        } else {
            JSONObject erroResult = new JSONObject();
            erroResult.put("error", "微信授权失败，请重新扫码");
            return Result.failure(SYSTEM_INNER_ERROR, erroResult);
        }


    }
}
